<?php

namespace App\Kuafu\Shop\Service;

use App\Exceptions\BaseException;
use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Config\Model\ConfigModel;
use App\Kuafu\Export\Jobs\QueueExport;
use App\Kuafu\Export\Model\ExportDownloadModel;
use App\Kuafu\Log\Model\OperateLogModel;
use App\Kuafu\Order\Service\OrderCodeService;
use App\Kuafu\Shop\Exceptions\ShopException;
use App\Kuafu\Shop\Model\AreaModel;
use App\Kuafu\Shop\Model\ShopDistributionBillRecordModel;
use App\Kuafu\Shop\Model\ShopDistributionModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class ShopDistributionService extends BaseService
{

    const SOURCE_TYPE_DISTRIBUTION = 1;// 分销渠道

    /**
     * 数量自增
     * @param int $shopId
     * @return mixed
     */
    public static function autoincrementByRedis(int $shopId)
    {
        $key = sprintf('distribution:' . '%s:%s', date('Ymd'), $shopId);

        $res = Redis::incr($key, 1);
        if ($res == 1) {
            Redis::expireAt($key, strtotime(date('Y-m-d')) + 86401);
        }
        return $res;
    }

    /**
     * 渠道新增
     * @param Request $request
     * @param int $shopId
     * @param int $userId
     * @throws BaseException
     */
    public static function addData(Request $request, int $shopId, int $userId)
    {
        try {

            $serialNo = 'SD' . date('YmdHis') . str_pad(self::autoincrementByRedis($shopId), 4, "0", STR_PAD_LEFT);

            $model                      = new ShopDistributionModel();
            $model->shopId              = $shopId;
            $model->serialNo            = $serialNo;
            $model->partnerName         = $request->partnerName ?? "";
            $model->provinceCode        = $request->provinceCode ?? 0;
            $model->cityCode            = $request->cityCode ?? 0;
            $model->countyCode          = $request->countyCode ?? 0;
            $model->detailInfo          = $request->detailInfo ?? "";
            $model->cooperationLeader   = $request->cooperationLeader ?? "";
            $model->mobile              = $request->mobile ?? "";
            $model->ratio               = $request->ratio ?? 0;
            $model->settlementCycleType = $request->settlementCycleType ?? 0;
            $model->minDeliveryAmount   = $request->minDeliveryAmount ?? 0;
            $model->status              = ShopDistributionModel::STATUS_DEFAULT;
            $model->createdByUid        = $userId;
            $model->createdAt           = time();
            $model->save();

            // 增加log
            OperateLogModel::add(
                OperateLogModel::MODULE_DISTRIBUTION,
                OperateLogModel::BUSINESS_DISTRIBUTION_UPDATE_RATIO,
                $model->id,
                $model->id,
                '新增渠道',
                json_encode(['ratio' => $model->ratio], JSON_UNESCAPED_UNICODE),
                OperateLogModel::STATUS_OK,
                $userId
            );
            return ['id' => $model->id];
        } catch (\Exception $exception) {
            handleException($exception, "渠道新增失败");
        }
    }

    /**
     * 渠道编辑
     * @param $request
     * @param int $id
     * @param int $shopId
     * @param int $userId
     * @throws BaseException
     */
    public static function updateData(Request $request, int $shopId, int $userId, int $id)
    {
        try {
            $info = ShopDistributionModel::query()
                                         ->where("shopId", $shopId)
                                         ->where('id', $id)
                                         ->first();
            if (!$info) {
                throw new ShopException(BaseCodeEnum::NOT_FOUND, '未找到记录');
            }
            $oldRatio = $info->ratio;
            $newRatio = $request->ratio ?? 0;

            $info->partnerName         = $request->partnerName ?? "";
            $info->provinceCode        = $request->provinceCode ?? 0;
            $info->cityCode            = $request->cityCode ?? 0;
            $info->countyCode          = $request->countyCode ?? 0;
            $info->detailInfo          = $request->detailInfo ?? "";
            $info->cooperationLeader   = $request->cooperationLeader ?? "";
            $info->mobile              = $request->mobile ?? "";
            $info->ratio               = $newRatio;
            $info->settlementCycleType = $request->settlementCycleType ?? 0;
            $info->minDeliveryAmount   = $request->minDeliveryAmount ?? 0;
            $info->updatedByUid        = $userId;
            $info->updatedAt           = time();
            $info->save();

            if ($oldRatio != $newRatio) {
                // 增加log
                OperateLogModel::add(
                    OperateLogModel::MODULE_DISTRIBUTION,
                    OperateLogModel::BUSINESS_DISTRIBUTION_UPDATE_RATIO,
                    $info->id,
                    $info->id,
                    '渠道编辑分佣比率',
                    json_encode(['oldRatio' => $oldRatio, 'newRatio' => $newRatio], JSON_UNESCAPED_UNICODE),
                    OperateLogModel::STATUS_OK,
                    $userId
                );
            }

        } catch (\Exception $exception) {
            handleException($exception, "渠道编辑失败");
        }
    }

    /**
     * 渠道详情
     * @param int $shopId
     * @param int $id
     * @return array
     */
    public static function info(int $shopId, int $id): array
    {
        $info = ShopDistributionModel::query()
                                     ->where("shopId", $shopId)
                                     ->where('id', $id)
                                     ->first();
        if (!$info) {
            return [];
        }
        $detailAddress = AreaModel::getAreaDetail($info->provinceCode, $info->cityCode, $info->countyCode);

        $info                            = $info->toArray();
        $info['settlementCycleTypeText'] = ShopDistributionModel::CYCLE_TYPE_MAPPING[$info['settlementCycleType']] ?? "";
        $info['statusText']              = ShopDistributionModel::CYCLE_TYPE_MAPPING[$info['status']] ?? "";
        $info['provinceName']            = $detailAddress->cnShortName ?? '';
        $info['cityName']                = $detailAddress->cityRel->cnShortName ?? '';
        $info['countyName']              = $detailAddress->cityRel->distinctRel->cnShortName ?? '';

        return $info;
    }


    public static function getEffectInfoById(int $id)
    {

        return ShopDistributionModel::query()
                                    ->select([
                                        'id',
                                        'partnerName',
                                        'detailInfo',
                                        'cooperationLeader',
                                        'mobile',
                                        'minDeliveryAmount',
                                        'ratio',
                                    ])
                                    ->where('id', $id)
                                    ->where('status', ShopDistributionModel::STATUS_DEFAULT)
                                    ->first();
    }

    /**
     * 渠道列表
     * @param int $shopId
     * @param int $pageSize
     * @param int $page
     * @param int $status
     * @return array
     */
    public static function list(
        int $shopId,
        int $pageSize,
        int $page,
        int $status = 0
    ): array {
        $paginate = ShopDistributionModel::query()
                                         ->when($shopId > 0, function ($query) use ($shopId) {
                                             $query->where("shopId", $shopId);
                                         })
                                         ->when($status, function ($query) use ($status) {
                                             $query->where("status", $status);
                                         })
                                         ->orderBy("id", "desc")
                                         ->paginate($pageSize, ['*'], "page", $page);

        $list = collect($paginate->items())->map(function ($item) {
            return [
                'id'                      => $item->id,
                'shopId'                  => $item->shopId,
                'serialNo'                => $item->serialNo,
                'partnerName'             => $item->partnerName,
                'provinceCode'            => $item->provinceCode,
                'cityCode'                => $item->cityCode,
                'countyCode'              => $item->countyCode,
                'detailInfo'              => $item->detailInfo,
                'cooperationLeader'       => $item->cooperationLeader,
                'mobile'                  => $item->mobile,
                'ratio'                   => $item->ratio,
                'settlementCycleType'     => $item->settlementCycleType,
                'settlementCycleTypeText' => ShopDistributionModel::CYCLE_TYPE_MAPPING[$item->settlementCycleType] ?? "",
                'minDeliveryAmount'       => $item->minDeliveryAmount,
                'status'                  => $item->status,
                'statusText'              => ShopDistributionModel::STATUS_MAPPING[$item->status] ?? "",
                'qrCodeUrl'               => $item->QrCodeUrl,
                'createdAt'               => $item->createdAt->toDateTimeString(),
            ];
        })->toArray();

        $defaultCount = ShopDistributionModel::getCount($shopId, ShopDistributionModel::STATUS_DEFAULT);
        $endCount     = ShopDistributionModel::getCount($shopId, ShopDistributionModel::STATUS_END);

        return [
            'lists' => [
                "page"     => $page,
                "total"    => $paginate->total(),
                "pageSize" => $pageSize,
                "list"     => $list,
            ],
            'total' => [
                'defaultCount' => $defaultCount,
                'endCount'     => $endCount,
            ]
        ];
    }

    /**
     * 渠道删除
     * @param int $id
     * @param int $shopId
     * @param int $userId
     * @throws BaseException
     */
    public static function delete(int $shopId, int $userId, int $id)
    {
        try {
            $info = ShopDistributionModel::query()
                                         ->where("shopId", $shopId)
                                         ->where('id', $id)
                                         ->first();
            if (!$info) {
                throw new ShopException(BaseCodeEnum::NOT_FOUND, '未找到记录');
            }

            $info->isDeleted    = 1;
            $info->updatedByUid = $userId;
            $info->updatedAt    = time();
            $info->save();

        } catch (\Exception $exception) {
            handleException($exception, "渠道删除失败");
        }
    }

    /**
     * 渠道删除
     * @param Request $request
     * @param int $shopId
     * @param int $userId
     * @param int $id
     * @throws BaseException
     */
    public static function updateStatus(Request $request, int $shopId, int $userId, int $id)
    {
        try {
            $info = ShopDistributionModel::query()
                                         ->where("shopId", $shopId)
                                         ->where('id', $id)
                                         ->first();
            if (!$info) {
                throw new ShopException(BaseCodeEnum::NOT_FOUND, '未找到记录');
            }
            if ($info->status != $request->status) {
                $info->status       = $request->status;
                $info->updatedByUid = $userId;
                $info->updatedAt    = time();
                $info->save();
            }
        } catch (\Exception $exception) {
            handleException($exception, "渠道状态变更失败");
        }
    }

    /**
     * 渠道分佣列表
     * @param int $shopId
     * @param int $distributionId
     * @return array
     */
    public static function historyBillList(int $shopId, int $distributionId): array
    {
        $list  = [];
        $total = [
            'amountTotal'    => 0,
            'brokerageTotal' => 0,
            'desc'           => '总计',
        ];
        $info  = ShopDistributionModel::query()
                                      ->where("shopId", $shopId)
                                      ->where('id', $distributionId)
                                      ->first();

        $settlementCycleType = $info->settlementCycleType ?? 1;

        // 查询时间一年内
        $startTime = strtotime(date('Y-m-d', strtotime('-1 year')));
        $endTime   = strtotime(date('Y-m-d'));

        ShopDistributionBillRecordModel::query()
                                       ->where("shopId", $shopId)
                                       ->where('distributionId', $distributionId)
                                       ->when($startTime && $endTime, function ($query) use ($startTime, $endTime) {
                                           $query->whereBetween('settlementCycleTime', [$startTime, $endTime]);
                                       })
                                       ->orderBy("id", "desc")
                                       ->chunkById(100, function ($item) use (&$total, &$list, $settlementCycleType) {
                                           foreach ($item as $v) {
                                               $settlementCycleTime = $v->settlementCycleTime ?? 0;
                                               if (!$settlementCycleTime) {
                                                   continue;
                                               }
                                               $amountTotal    = $v->amount ?? 0;
                                               $brokerageTotal = $v->brokerage ?? 0;
                                               if ($settlementCycleType == ShopDistributionModel::CYCLE_TYPE_WEEK) {
                                                   $getDayInWeek = self::getDayInWeek($settlementCycleTime);
                                                   $startTime    = $getDayInWeek['startTime'] ? date('Y.md',
                                                       strtotime($getDayInWeek['startTime'])) : '';
                                                   $endTime      = $getDayInWeek['endTime'] ? date('Y.md',
                                                       strtotime($getDayInWeek['endTime'])) : '';
                                                   if (!($startTime && $endTime)) {
                                                       continue;
                                                   }
                                                   $k = $startTime . '-' . $endTime;
                                               } else {
                                                   $k = date('Y-m', $settlementCycleTime);
                                               }
                                               if (isset($list[$k])) {
                                                   $list[$k]['amountTotal']    += $amountTotal;
                                                   $list[$k]['brokerageTotal'] += $brokerageTotal;
                                               } else {
                                                   $list[$k] = [
                                                       'amountTotal'    => $amountTotal,
                                                       'brokerageTotal' => $brokerageTotal,
                                                       'desc'           => $k,
                                                   ];
                                               }
                                               $total['amountTotal']    += $amountTotal;
                                               $total['brokerageTotal'] += $brokerageTotal;
                                           }

                                       });

        if ($list) {
            foreach ($list as &$v) {
                $v['amountTotal']    = bcdiv($v['amountTotal'], 100, 2);
                $v['brokerageTotal'] = bcdiv($v['brokerageTotal'], 100, 2);
            }
        }
        $total['amountTotal']    = bcdiv($total['amountTotal'], 100, 2);
        $total['brokerageTotal'] = bcdiv($total['brokerageTotal'], 100, 2);
        return ["list" => array_merge([$total], array_values($list))];
    }

    /**
     * 通过一个时间查询出当前周一到周日时间
     * @param int $settlementCycleTime
     * @return array
     */
    public static function getDayInWeek(int $settlementCycleTime): array
    {
        $startTime = '';//周一
        $endTime   = '';//周日
        $week      = date('w', $settlementCycleTime);
        switch ($week) {
            case 1:// 星期1
                $startTime = date('Y-m-d', $settlementCycleTime);//周一
                break;
            case 2:// 星期2
                $startTime = date('Y-m-d', $settlementCycleTime - 86400);//周一
                break;
            case 3:// 星期3
                $startTime = date('Y-m-d', $settlementCycleTime - 2 * 86400);//周一
                break;
            case 4:// 星期4
                $startTime = date('Y-m-d', $settlementCycleTime - 3 * 86400);//周一
                break;
            case 5:// 星期5
                $startTime = date('Y-m-d', $settlementCycleTime - 4 * 86400);//周一
                break;
            case 6:// 星期6
                $startTime = date('Y-m-d', $settlementCycleTime - 5 * 86400);//周一
                break;
            case 0:// 星期天
                $startTime = date('Y-m-d', $settlementCycleTime + 86400);//周一
                break;
        }
        if ($startTime) {
            $endTime = date('Y-m-d', (strtotime($startTime) + 7 * 86400) - 1);//周日
        }
        return [
            'startTime' => $startTime,
            'endTime'   => $endTime,
        ];
    }

    /**
     * 渠道生成二维码
     * @param int $shopId
     * @param int $distributionId
     * @param int $userId
     * @return array
     */
    public static function genDistributionOrderCode(int $shopId, int $distributionId, int $userId): array
    {
//        $res = self::genDistributionOrderCodeImg($shopId, $distributionId, $userId);dd($res);
        $export = (new ExportDownloadModel)->add(ExportDownloadModel::CLIENT_TYPE_APP,
            ExportDownloadModel::FILE_TYPE_APP_DISTRIBUTION_QRCODE, [
                'shopId'         => $shopId,
                'distributionId' => $distributionId,
                'userId'         => $userId,
                'needCode'       => false,
                'sourceType'     => self::SOURCE_TYPE_DISTRIBUTION,
                'showStartAt'    => time(),
                'showEndAt'      => time(),
            ]);

        dispatch(new QueueExport($export->id))->onQueue(QueueExport::QUEUE_SOURCE_MATERIAL_TEMPLATE_NAME);
        return [];
    }

    /**
     * 保存渠道生成二维码
     * @param int $shopId
     * @param int $distributionId
     * @param int $userId
     * @param bool $needCode
     * @param int $sourceType
     * @return array
     */
    public static function genDistributionOrderCodeImg(
        int $shopId,
        int $distributionId,
        int $userId,
        bool $needCode = false,
        int $sourceType = 1
    ): array {
        try {
            $data   = OrderCodeService::genDistributionOrderCode($shopId, $distributionId, $needCode, $sourceType);
            $config = ConfigModel::getConfigByTypeKeyOne('merchant', 'distributionQrcode');
            $info   = [
                'id'    => 10000,
                'value' => $config->value,
            ];

            $shopDistribution = self::info($shopId, $distributionId);

            $createTemplateData['wechatUrl']          = $data['fullUrl'] ?? '';
            $createTemplateData['recruitmentRequire'] = $shopDistribution['partnerName'] ?? '';
            return (new ToolsService())->generateTemplateImg($info, $createTemplateData, $userId, $shopId);
        } catch (\Exception $e) {
            Log::error('genDistributionOrderCodeImg err:', [
                'shopId'         => $shopId,
                'distributionId' => $distributionId,
                'userId'         => $userId,
                'needCode'       => $needCode,
                'sourceType'     => $sourceType,
                'msg'            => $e->getMessage(),
            ]);
            return [];
        }
    }

    /**
     * 渠道列表
     * @param int $shopId
     * @param int $status
     * @return array
     */
    public static function searchList(
        int $shopId,
        int $status = ShopDistributionModel::STATUS_DEFAULT
    ): array {
        $list = [];
        ShopDistributionModel::query()
                             ->when($shopId > 0, function ($query) use ($shopId) {
                                 $query->where("shopId", $shopId);
                             })
                             ->when($status, function ($query) use ($status) {
                                 $query->where("status", $status);
                             })
                             ->orderBy("id", "desc")
                             ->chunkById(100, function ($item) use (&$list) {
                                 foreach ($item as $v) {
                                     $list[] = [
                                         'id'          => $v->id,
                                         'partnerName' => $v->partnerName,
                                     ];
                                 }
                             });
        return $list;
    }
}
